package cn.com.bod.fas.clm.service.impl;

import cn.com.bod.fas.clm.common.ConNoGeneration;
import cn.com.bod.fas.clm.constant.enumconst.ConStatusEnum;
import cn.com.bod.fas.clm.dao.mapper.*;
import cn.com.bod.fas.clm.model.po.CnLoanConPo;
import cn.com.bod.fas.clm.service.CnConService;
import cn.com.bod.fas.common.utils.UserInfoUtil;
import cn.com.bod.fas.clm.api.model.vo.dto.request.InitConRequVo;
import cn.com.bod.fas.clm.api.model.vo.dto.request.PbBaseInfoRequVo;
import cn.com.bod.fas.clm.api.model.vo.dto.response.LoanConBaseRespVo;
import cn.com.bod.fas.clm.api.service.CnConApiService;
import cn.com.bod.fas.clm.constant.enumconst.ConTypeEnum;
import cn.com.bod.fas.clm.constant.enumconst.GuarConTypeEnum;
import cn.com.bod.fas.clm.constant.enumconst.RelaStatusEnum;
import cn.com.bod.fas.clm.model.po.CnGuarConPo;
import cn.com.bod.fas.clm.model.po.CnGuarPledgeRelaPo;
import cn.com.bod.fas.clm.model.po.CnLoanGuarRelaPo;
import cn.com.bod.fas.clm.model.vo.dto.request.SignConRequVo;
import cn.com.bod.fas.clm.model.vo.dto.response.ConListRespVo;

import cn.com.yusys.yusp.commons.util.BeanUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @description 合同签订业务实现
 * @author shihf
 * @date 2019年09月18日 11时35分09秒
 * @version 1.0.0
 * @Copyright (c) scfhdt
 */
@Service
public class CnConServiceImpl implements CnConService, CnConApiService {

    @Autowired
    private CnLoanConMapper cnLoanConMapper; // 贷款合同
    @Autowired
    private CnGuarConMapper cnGuarConMapper; // 担保合同
    @Autowired
    private CnLoanGuarRelaMapper cnLoanGuarRelaMapper; // 贷款与担保合同关系
    @Autowired
    private CnGuarPledgeRelaMapper cnGuarPledgeRelaMapper; // 担保与押品关系
    @Autowired
    private CnConMapper cnConMapper; // 合同签订业务
    @Autowired
    private UserInfoUtil userInfoUtil; // 用户信息

    /**
     * @description 初始化合同信息
     * @author shihf
     * @date 2019年09月18日 11:36
     * @param initConRequVo 自动初始化入参
     * @return String 贷款合同编号
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public String initCon(InitConRequVo initConRequVo) {
        // 1.生成贷款合同信息
        CnLoanConPo cnLoanConPo = BeanUtil.beanCopy(initConRequVo, new CnLoanConPo());
        // 设置贷款合同编号
        String loanConNo = ConNoGeneration.getConNo(ConTypeEnum.LOAN.getCode());
        cnLoanConPo.setLoanConNo(loanConNo);
        cnLoanConPo.setCertTypeId(initConRequVo.getCertTypeId());
        cnLoanConPo.setCertNo(initConRequVo.getCertNo());
        // 设置签订状态 01未签订，02已签订，03作废
        cnLoanConPo.setConStatus(ConStatusEnum.NO_SIGN.getCode());
        userInfoUtil.setCreator(cnLoanConPo);
        cnLoanConMapper.insert(cnLoanConPo);
        // 2.获取押品信息
        List<PbBaseInfoRequVo> pdBaseInfoVos = initConRequVo.getPdBaseInfoVos();
        // 将押品按客户号分组
        Map<String, List<PbBaseInfoRequVo>> pbBaseInfoRequVoListMap =
                pdBaseInfoVos.stream().collect(Collectors.groupingBy(PbBaseInfoRequVo::getRelaCustNo));
        // 3.创建担保合同信息，并建立关系
        ArrayList<CnGuarConPo> cnGuarConPos = new ArrayList<>();
        ArrayList<CnGuarPledgeRelaPo> cnGuarPledgeRelaPos = new ArrayList<>();
        ArrayList<CnLoanGuarRelaPo> cnLoanGuarRelaPos = new ArrayList<>();

        // relaCustNo->押品客户号=担保人客户号  PbBaseInfoRequVoList->押品列表
        pbBaseInfoRequVoListMap.forEach((relaCustNo,pbBaseInfoRequVoList) -> {
            // 一组押品客户号相同的押品信息，生成一个担保合同编号
            String guarConNo = ConNoGeneration.getConNo(ConTypeEnum.GUAR.getCode());
            // 担保人客户名称
            String guarCustName = pbBaseInfoRequVoList.get(0).getOwnerName();
            // 计算担保金额
            BigDecimal guarAmt = pbBaseInfoRequVoList.stream().map(PbBaseInfoRequVo::getEstimAmt).reduce(BigDecimal::add).get();
            // 担保与押品关系信息
            pbBaseInfoRequVoList.forEach(item -> {
                CnGuarPledgeRelaPo cnGuarPledgeRelaPo = new CnGuarPledgeRelaPo();
                cnGuarPledgeRelaPo.setPledgeNo(item.getPledgeNo());
                cnGuarPledgeRelaPo.setGuarConNo(guarConNo);
                cnGuarPledgeRelaPo.setFinOrgId(initConRequVo.getFinOrgId());
                userInfoUtil.setCreator(cnGuarPledgeRelaPo);
                cnGuarPledgeRelaPos.add(cnGuarPledgeRelaPo);
            });
            // 担保合同信息
            CnGuarConPo guarConPo = new CnGuarConPo();
            guarConPo.setGuarConNo(guarConNo); // 担保合同编号
            guarConPo.setFinOrgId(initConRequVo.getFinOrgId()); // 金融机构
            guarConPo.setGuarConTypeId(GuarConTypeEnum.GENERAL.getCode()); // 合同类型
            guarConPo.setLoanCustNo(initConRequVo.getCustNo()); // 借款人客户号
            guarConPo.setLoanCustName(initConRequVo.getCustName()); // 借款人客户名称
            guarConPo.setGuarCustNo(relaCustNo); // 担保人客户号
            guarConPo.setGuarCustName(guarCustName); // 担保人客户名称
            guarConPo.setGuarAmt(guarAmt); // 担保金额
            guarConPo.setGuarBal(guarAmt); // 担保可用金额
            guarConPo.setGuarTermTypeId(initConRequVo.getLoanTermTypeId()); // 担保期限类型
            guarConPo.setGuarTerm(initConRequVo.getConTerm()); // 担保期限
            guarConPo.setGuarConStatus(ConStatusEnum.NO_SIGN.getCode()); // 状态
            userInfoUtil.setCreator(guarConPo);
            cnGuarConPos.add(guarConPo);
            // 贷款合同与担保合同关系信息
            CnLoanGuarRelaPo cnLoanGuarRelaPo = new CnLoanGuarRelaPo();
            cnLoanGuarRelaPo.setLoanConNo(loanConNo);
            cnLoanGuarRelaPo.setGuarConNo(guarConNo);
            cnLoanGuarRelaPo.setFinOrgId(initConRequVo.getFinOrgId());
            cnLoanGuarRelaPo.setRelaStatus(RelaStatusEnum.EFFECTIVE.getCode());
            userInfoUtil.setCreator(cnLoanGuarRelaPo);
            cnLoanGuarRelaPos.add(cnLoanGuarRelaPo);
        });
        // 入库
        cnGuarConMapper.insertBatch(cnGuarConPos);
        cnLoanGuarRelaMapper.insertBatch(cnLoanGuarRelaPos);
        cnGuarPledgeRelaMapper.insertBatch(cnGuarPledgeRelaPos);
        return loanConNo;
    }

    /**
     * @description 合同签订
     * @author shihf
     * @date 2019年09月21日 14:12
     * @param signConRequVo
     * @return void
     */
    @Override
    public void signCon(SignConRequVo signConRequVo) {
        // 1.判断合同类型
        if(signConRequVo.getConType().equals(ConTypeEnum.LOAN.getCode())) {
            // 2.修改合同状态
            CnLoanConPo cnLoanConPo =  new CnLoanConPo();
            cnLoanConPo.setLoanConNo(signConRequVo.getConNo());
            cnLoanConPo.setConDueDate(signConRequVo.getConDueDate());
            cnLoanConPo.setConSignDate(signConRequVo.getConSignDate());
            cnLoanConPo.setConSignOrgName(signConRequVo.getConSignOrgName());
            cnLoanConPo.setConSignUserName(signConRequVo.getConSignUserName());
            cnLoanConPo.setConStartDate(signConRequVo.getConStartDate());
            cnLoanConPo.setConStatus(ConStatusEnum.SIGN.getCode()); // 已签订
            cnLoanConMapper.updateByLoanConNo(cnLoanConPo);
        } else {
            CnGuarConPo guarCon = new CnGuarConPo();
            guarCon.setGuarConNo(signConRequVo.getConNo());
            guarCon.setGuarDueDate(signConRequVo.getConDueDate());
            guarCon.setSignDate(signConRequVo.getConSignDate());
            guarCon.setSignOrgName(signConRequVo.getConSignOrgName());
            guarCon.setSignPerName(signConRequVo.getConSignUserName());
            guarCon.setGuarStartDate(signConRequVo.getConStartDate());
            guarCon.setGuarConStatus(ConStatusEnum.SIGN.getCode()); // 已签订
            cnGuarConMapper.updateByGuarConNo(guarCon);
        }
    }

    /**
     * @description 根据贷款申请号查询合同列表
     * @author shihf
     * @date 2019年09月26日 11:36
     * @param loanApplyNo 贷款申请号
     * @return  List<ConListRespVo> 合同列表
     */
    @Override
    public List<ConListRespVo> selectConListByLoanApplyNo(Long loanApplyNo) {
        List<ConListRespVo> conListRespVos = cnConMapper.selectConListByLoanApplyNo(loanApplyNo);
        return conListRespVos;
    }

    /**
     * @description 合同详情接口
     * @author shihf
     * @date 2019年10月16日 14:24
     * @param loanConNo
     * @return cn.com.scfhdt.contract.api.model.vo.dto.response.LoanConBaseRespVo
     */
    @Override
    public LoanConBaseRespVo getLoanConBase(String loanConNo) {
        CnLoanConPo cnLoanConPo = cnConMapper.selectConBaseByConNo(loanConNo);
        LoanConBaseRespVo loanConBaseRespVo = BeanUtil.beanCopy(cnLoanConPo, LoanConBaseRespVo.class);
        return loanConBaseRespVo;
    }

}
